package com.yang;

import org.neo4j.driver.*;
import org.neo4j.driver.Record;
import java.util.ArrayList;


public class BookMarkTest implements AutoCloseable {
    private final Driver driver;

    public BookMarkTest(String url, String user, String password) {
        this.driver = GraphDatabase.driver(url, AuthTokens.basic(user,password));
    }

    public static void main(String[] args) throws Exception {
        try(BookMarkTest bookMarkTest= new BookMarkTest("bolt://192.168.1.21:7687","neo4j","neo4jneo4j")) {
            bookMarkTest.addEmployAndMakeFriends();
        }
    }

    public void addEmployAndMakeFriends(){
        ArrayList<Bookmark> savedBookmarks = new ArrayList<>();
        //创建第一个人和雇佣关系
        try(Session session=driver.session(SessionConfig.builder().withDefaultAccessMode(AccessMode.WRITE).build())){
            session.writeTransaction(tx->addCompany(tx,"Wayne Enterprises"));
            session.writeTransaction(tx->addPerson(tx,"Alice"));
            session.writeTransaction(tx->employ(tx,"Alice","Wayne Enterprises"));
            savedBookmarks.add(session.lastBookmark());
        }

        //创建第二个人和雇佣关系
        try(Session session2=driver.session(SessionConfig.builder().withDefaultAccessMode(AccessMode.WRITE).build())) {
            session2.writeTransaction(tx->addCompany(tx,"LexCorp"));
            session2.writeTransaction(tx->addPerson(tx,"Bob"));
            session2.writeTransaction(tx->employ(tx,"Bob","LexCorp"));

            savedBookmarks.add(session2.lastBookmark());
        }
        //创建两个人之间的关系
        try(Session session3=driver.session(SessionConfig.builder().withDefaultAccessMode(AccessMode.WRITE).withBookmarks(savedBookmarks).build())) {
            session3.writeTransaction(tx->makeFriends(tx,"Alice","Bob"));
            session3.readTransaction(this::printFriends);
        }
    }

    /**
     * 添加公司节点
     *
     * @param tx         事务
     * @param companyName 公司名称
     */
    private Void addCompany(Transaction tx, String companyName) {
        String query = "MERGE (c:Company {name: $name})";
        tx.run(query, Values.parameters("name", companyName));
        return null;
    }

    /**
     * 添加人员节点
     *
     * @param tx         事务
     * @param personName 人员名称
     */
    private Void addPerson(Transaction tx, String personName) {
        String query = "MERGE (p:Person {name: $name})";
        tx.run(query, Values.parameters("name", personName));
        return null;
    }

    /**
     * 建立人员与公司的雇佣关系
     *
     * @param tx           事务
     * @param personName   人员名称
     * @param companyName  公司名称
     */
    private Void employ(Transaction tx, String personName, String companyName) {
        String query = "MATCH (p:Person {name: $personName}), (c:Company {name: $companyName}) " +
                "MERGE (p)-[:EMPLOYED_BY]->(c)";
        tx.run(query, Values.parameters("personName", personName, "companyName", companyName));
        return null;
    }

    /**
     * 建立两个人之间的友谊关系
     *
     * @param tx        事务
     * @param person1   第一个人
     * @param person2   第二个人
     */
    private Void makeFriends(Transaction tx, String person1, String person2) {
        String query = "MATCH (p1:Person {name: $person1}), (p2:Person {name: $person2}) " +
                "MERGE (p1)-[:FRIEND]->(p2)";
        tx.run(query, Values.parameters("person1", person1, "person2", person2));
        return null;
    }

    /**
     * 打印所有人的朋友列表
     *
     * @param tx 事务
     * @return Void
     */
    private Void printFriends(Transaction tx) {
        String query = "MATCH (p:Person)-[:FRIEND]->(f:Person) RETURN p.name AS person, f.name AS friend";
        Result result = tx.run(query);
        System.out.println("Friends List:");
        while (result.hasNext()) {
            Record record = result.next();
            String person = record.get("person").asString();
            String friend = record.get("friend").asString();
            System.out.println(person + " is friends with " + friend);
        }
        return null;
    }

    @Override
    public void close() throws Exception {
        this.driver.close();
    }

}
